home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload Trio 2
/
Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO
/
dir39
/
cmos16.zip
/
CMOS.ASM
< prev
next >
Wrap
Assembly Source File
|
1994-08-28
|
16KB
|
675 lines
PAGE 60,132
NAME CMOSSAVE
TITLE CMOSSave Save CMOS to a file on disk or floppy
Comment |
Version 1.6 1994 Augest 29 Roedy Green
works with MASM 6.0 and Optasm
This assembler code generates all three programs:
CMOSSAVE.COM CMOSREST.COM and CMOSCHK.COM.
See CMOS.TXT for details on use.
USAGE:
Examples:
*********
CMOSSave A:\MyCMOS.Sav
CMOSRest A:\MyCMOS.Sav
CMOSChk A:\ByCMOS.Sav
Syntax errors or missing file trouble generates an ERRORLEVEL 4.
CMOSChk generates an ERRORLEVEL 1 if the CMOS has changed since
the CMOSSave was done.
Version History
***************
Version 1.0
- released to BIX 91/09/07
Version 1.1
- released to BIX 91/09/18
- added special check for small 64 character CMOSes.
Version 1.2
- fix spelling errors
- use CMOS.SAV instead of MyCMOS.SAV in examples
Version 1.3
- now consider fewer bytes volatile, restore more stuff.
- hints in docs about clearing CMOS.
Version 1.4
- now consider flags Status register C, offset 0C as volatile.
fixes false alarms.
Version 1.5 1994 June 1
- change of address and phone number
- address now appears in the banner.
Version 1.6 1994 August 29
- more information about how CMOS bits are used.
CMOS Usage - see also CMOS.OFS
How to Assemble
***************
Manually set the GENERATING equate embedded in this code, then:
to assemble with MASM 6.0 use:
ML.EXE /AT /c /Fl /VM /Zf /Zm CMOS.Asm
LINK.EXE /TINY /MAP CMOS.Obj,CMOS.com,CMOS.map;
copy cmos.com cmossave.com
to assemble with OPTASM use:
Optasm CMOS.Asm,CMOS.Obj,CMOS.Lst/L/N/G/S
OLINK CMOS.Obj,CMOS.COM,/MAP/TINY;
copy cmos.com cmossave.com
Register Conventions
********************
Subroutines may trash all registers except those explicity
documented as input or output.
| ; end of comment
; E Q U A T E S
CMOSSAVE EQU 1
CMOSREST EQU 2
CMOSCHK EQU 3
; use /DGenerating#CMOSSAVE
; /DGenerating#CMOSREST
; /DGenerating#CMOSCHK
; on the assembler command line to select which version
; of the code to assemble.
; Or add code following of the form:
; GENERATING EQU CMOSSave
If Generating eq CMOSSave
%OUT Generating CMOSSave.Com
Endif
If Generating eq CMOSRest
%OUT Generating CMOSRest.Com
endif
If Generating eq CMOSChk
%OUT Generating CMOSChk.Com
endif
;==============================================================
stack segment stack ; keep MS link happy by providing null stack
stack ends
CODE SEGMENT PARA ; start off in code.
;==============================================================
data segment byte ; provide a separate DATA segment
; actually all come after the code
;==============================================================
; V A R I A B L E S
If Generating eq CMOSSave
BannerMsg DB '░▒▓█ CMOSSave 1.6 █▓▒░',13d,10d
DB 13d,10d
DB 'Saves contents of CMOS to a file on hard disk or floppy.',13,10
DB 'Copyright (c) 1991,1994 Roedy Green Canadian Mind Products (604) 685-8412.',13,10
DB '#601 - 1330 Burrard, Vancouver BC CANADA V6Z 2B8',13,10
DB 'Shareware to freely distribute and use for any purpose except military.',13,10
DB 13,10
db '$'
UsageMsg DB '░▒▓█ Error █▓▒░',7,13,10
DB 'Insert a formatted diskette.',13,10
DB 'then try:',13,10
DB 'CMOSSave A:\CMOS.Sav',13,10
DB 'or if want to save on hard disk try:',13,10
DB 'CMOSSave C:\CMOS.Sav',13,10
DB 'Read CMOS.TXT to find how to use it properly.',13,10
db '$'
FileTroubleMsg DB '░▒▓█ Error █▓▒░',7,13,10
DB 'Cannot create the disk file.',13,10
db '$'
WorkedMsg DB 'CMOS successfully saved',13,10
db '$'
EndIf
If Generating eq CMOSRest
BannerMsg DB '░▒▓█ CMOSRest 1.6 █▓▒░',13d,10d
DB 13d,10d
DB 'Restores CMOS from a CMOSSave file on hard disk or floppy.',13,10
DB 'Copyright (c) 1991,1994 Roedy Green Canadian Mind Products (604) 685-8412.',13,10
DB '#601 - 1330 Burrard, Vancouver BC CANADA V6Z 2B8',13,10
DB 'Shareware to freely distribute and use for any purpose except military.',13,10
DB 13,10
db '$'
UsageMsg DB '░▒▓█ Error █▓▒░',13,10
DB 'Insert the diskette you used for CMOSSave.',13,10
DB 'then try:',13,10
DB 'CMOSRest A:\CMOS.Sav',13,10
DB 'or if the file is on hard disk try:',13,10
DB 'CMOSRest C:\CMOS.Sav',13,10
DB 'Read CMOS.TXT to find how to use it properly.',13,10
db '$'
FileTroubleMsg DB '░▒▓█ Error █▓▒░',7,13,10
DB 'Cannot find/read the disk file.',13,10
db '$'
WorkedMsg DB 'CMOS successfully restored',13,10
db '$'
EndIf
If Generating eq CMOSChk
BannerMsg DB '░▒▓█ CMOSChk 1.6 █▓▒░',13d,10d
DB 13d,10d
DB 'Ensures CMOS not corrupted or changed.',13,10
DB 'Copyright (c) 1991,1994 Roedy Green Canadian Mind Products (604) 685-8412.',13,10
DB '#601 - 1330 Burrard, Vancouver BC CANADA V6Z 2B8',13,10
DB 'Shareware to freely distribute and use for any purpose except military.',13,10
DB 13,10
db '$'
UsageMsg DB '░▒▓█ Error █▓▒░',7,13,10
DB 'Insert the diskette you used for CMOSSave.',13,10
DB 'then try:',13,10
DB 'CMOSChk A:\CMOS.Sav',13,10
DB 'or if you have the file on hard disk try:',13,10
DB 'CMOSChk C:\CMOS.Sav',13,10
DB 'Read CMOS.TXT to find how to use it properly.',13,10
db '$'
FileTroubleMsg DB '░▒▓█ Error █▓▒░',7,13,10
DB 'Cannot find/read the disk file.',13,10
db '$'
MatchTroubleMsg DB '░▒▓█ Error █▓▒░',7,13,10
DB 'CMOS has been corrupted!',13,10
db '$'
WorkedMsg DB 'CMOS is OK, i.e. unchanged since the last CMOSSave.',13,10
db '$'
EndIf
FilenamePtr DW 0
; pointer to filename in command line
CMOSSize DB 0
; size of cmos in bytes
CMOSBuff db 0 ; dynamic buffer will grow to 128
; it hangs out past the end of the program
data ends
com group code,data ; force data segment to go at the end
ASSUME CS:com,DS:com,ES:com,SS:com
; seg regs cover everything
ORG 100H ; in Code segment
;==========================
Main proc far
; M A I N L I N E R O U T I N E
Start:
lea dx,BannerMsg ; display the banner
Call Say
Call Parse ; get filename from command line
If Generating eq CMOSSave
call GetCMOS ; fetch CMOS to buffer
call WriteCMOS ; write CMOS contents to file
EndIf
If Generating eq CMOSRest
call ReadCMOS ; read CMOS contents from file
call CalcCMOSSize ; it is 64 or 128 bytes long?
call PutCMOS ; store buffer to CMOS
EndIf
If Generating eq CMOSChk
call ReadCMOS ; read CMOS contents from file
call CalcCMOSSize ; it is 64 or 128 bytes long?
call CompareCMOS ; compare CMOS with buffer
EndIf
lea dx,WorkedMsg ; crow about success
Call Say
Done:
mov ax,4c00h
int 21h ;normal termination
Main EndP
;===============================================================
Trouble proc near
FileTrouble:
Lea dx,FileTroubleMsg ; display file trouble
Call Say
Jmp Abort
abort:
; error exit
mov ax, 4c04h ; ERRORLEVEL = 4
int 21h ; DIE
Trouble endp
;===============================================================
MLeading PROC Near
; Remove leading blanks
; on entry BX is addr of string, CX its length
; trims off any leading blanks, leaving result in BX CX
; length may also be 0 or 1, but not -ve
; If the entire string is blank the result is the null string
mov di,bx
mov al,20H ; AL = blank -- the search char
jcxz mleading2 ; jump if null string
repe scasb ; scan ES:DI forwards till hit non blank
; DI points just after it (wrap ok)
; cx IS ONE TOO SMALL, OR 0 IF NONE FOUND
je mleading1 ; jump if entire string was blank
inc cx ; CX is length of remainder of string
mleading1:
dec di ; DI points to non-blank
mleading2:
mov bx,di ; put address back
ret
MLeading ENDP
;========================================
MTrailing PROC Near
; Remove trailing blanks.
; on entry BX is addr of string, CX its length
; trims off any trailing blanks, leaving result in BX CX
; length may also be 0 or 1, but not -ve
; If the entire string is blank the result is the null string
mov di,bx
add di,cx ; calc addr last char in string
dec di
mov al,20H ; AL = blank -- the search char
jcxz mtrailing1 ; jump if null string
std
repe scasb ; scan ES:DI backwards till hit non blank
; DI points just ahead of it (wrap ok)
; CX is one too small, or 0 if none found
cld
je mtrailing1 ; jump if whole string was blank
inc cx
mtrailing1:
ret
MTrailing ENDP
;========================================
Parse PROC NEAR
; Parse the command line to remove lead/trail blanks from
; the single drive parameter and terminate it by 2 nulls.
; sample inputs
; CMOSRest A:\CMOS.SAV
; CMOSRest B:\MySub\MyCMOS.SAV
;
; When Done DS:BX points to start of string.
; String will be terminated by 2 nulls
; CX counts bytes in string exclusive of nulls
; counted string at HEX 80 PSP
; contains command line.
; Preceeded by unwanted spaces.
; possibly followed by unwanted spaces.
; currently missing a trailing null.
xor ch,ch
mov cl,ds:80H
mov bx,81H
call Mleading ; get rid of leading blanks
call MTrailing ; get rid of trailing blanks
mov di,bx ; calc addr of byte just past end
add di,cx
mov word ptr [di],0 ; plop in pair of nulls after string
mov FileNamePtr,bx ; remember where filename was
jcxz SyntaxTrouble ; missing parm.
ret
SyntaxTrouble:
lea dx,UsageMsg ; display usage message
Call Say
Jmp Abort
Parse ENDP
;======================================
Say Proc
; on entry DX points to a string to display
MOV AH,9
Int 21h
ret
Say EndP
;======================================
If Generating eq CMOSSave
GetCMOS Proc Near
; Get 128 byte contents of CMOS into a buffer.
mov cx,128 ; count of times through loop
lea bx,CMOSBuff ; where to put the contents
sub al,al ; start offset in CMOS
GetLoop:
Call PeekCmos ; al=offset ah=contents
mov byte ptr[bx],ah
inc al
inc bx
loop GetLoop
ret
GetCMOS EndP
EndIf
;===============================================================
If Generating eq CMOSRest
PutCMOS Proc Near
; Put 128-byte contents of buffer into CMOS.
; do not touch the volatile bytes
mov cx,128 ; count of times through loop
lea bx,CMOSBuff ; where to put the contents
sub al,al ; start offset in CMOS
PutLoop:
call Volatile ; test if this is a volatile byte
; test offset in al
jc LeaveItAlone
mov ah,byte ptr[bx]
Call PokeCMOS ; al=offset ah=contents
LeaveItAlone:
inc bx
inc al
loop PutLoop
ret
PutCMOS EndP
EndIf
;===============================================================
If Generating eq CMOSChk
CompareCMOS proc Near
; compares buffer version of CMOS with contents of actual CMOS
; ignores mismatches of volatile bytes.
; Aborts if finds a mismatch
mov cx,128 ; count of times through loop
lea bx,CMOSBuff ; where to find comparison set
sub al,al ; start offset in CMOS
CompLoop:
call Volatile ; test if this is a volatile byte
; test offset in al
jc IgnoreMismatch
Call PeekCMOS ; al=offset ah=contents
cmp ah,byte ptr[bx] ; compare CMOS with buffer
jne MatchTrouble
IgnoreMismatch:
inc bx
inc al
loop CompLoop
ret
MatchTrouble:
lea dx,MatchTroubleMsg ; display CMOS mismatch
call Say
mov ax, 4c01h ; ERRORLEVEL = 1
int 21h ; DIE
CompareCMOS EndP
EndIf
;===============================================================
If Generating ne CMOSSave
Volatile Proc near
; Is cmos offset in AL volatile? If so set carry.
; These bytes will be undisturbed.
; Preserves all registers.
; 00..09, 0C and 32 are volatile, rest are not.
; 0A 0B 0D 0E 0F used to be considered volatile, now are not.
; if cmos is small, all bytes past end are considered volatile
cmp al,CMOSSize ; bytes past end are volatile
jae IsVolatile
cmp al,09h
jbe IsVolatile ; early bytes are for timing
cmp al,0Ch ; flags status register
je IsVolatile ; is considered volatile
cmp al,32h ; 32 is date century byte,
je IsVolatile ; not exactly volatile, but ...
IsNotVolatile:
clc ; clear carry
ret
IsVolatile:
stc
ret
Volatile EndP
EndIf
;===============================================================
If Generating ne CMOSSave
CalcCMOSSize Proc near
; Is CMOS 64 or 128 bytes long?
; It is 64 if bytes at 10..2F match those at 50..6F.
; Otherwise it is 128 bytes.
; Preserves all registers.
push si
push di
push cx
lea si,CMOSBuff+10h
lea di,CMOSBuff+50h
mov cx,02fh+1-10h
repe cmpsb
je IsCMOS64
IsCMOS128:
mov CMOSSize,128 ; differ, must be a big CMOS
jmp CalcCMOSSizeDone
IsCMOS64:
mov CMOSSize,64 ; all same, small CMOS
CalcCMOSSizeDone:
pop cx
pop di
pop si
ret
CalcCMOSSize EndP
EndIf
;===============================================================
if Generating ne CMOSRest
PeekCMOS proc near
; Reads one byte from cmos.
; on entry al has offset desired
; on exit ah has the contents of that byte.
; preserves all registers
; See page 5-81 IBM AT Tech ref BIOS listing for how to read CMOS
; We always enable the NMI with bit 7 on.
push bx
push ax
cli ; disable interrupts
or al,80h ; disable NMI
out 70h,al ; output the byte address to CMOS
jmp $+2 ; delay, safer than nop
in al,71h ; read the CMOS byte
jmp $+2 ; delay, safer than nop
mov bl,al
; re-enable the NMI
mov al,0dh ; point to battery status register
out 70h,al ; leave pointing at a safe r/o register
sti ; restore interrupts
pop ax
mov ah,bl
pop bx
ret
PeekCMOS EndP
EndIf
;===============================================================
If Generating eq CMOSRest
PokeCMOS proc near
; Stuffs one byte into cmos.
; on entry al has offset desired, ah has the value to stuff.
; Preserves all registers.
; See page 5-81 IBM AT Tech ref BIOS listing for how to write CMOS
; We always enable the NMI with bit 7 on.
push ax
cli ; disable interrupts
or al,80h ; disable NMI
out 70h,al ; output the byte address to CMOS
jmp $+2 ; delay, safer than nop
mov al,ah ; get contents
out 71h,al ; poke the CMOS byte
jmp $+2 ; delay, safer than nop
; re-enable the NMI
mov al,0dh ; point to battery status register
out 70h,al ; leave pointing at a safe r/o register
sti ; restore interrupts
pop ax
ret
PokeCMOS EndP
EndIf
;===============================================================
If Generating ne CMOSSave
ReadCMOS Proc Near
; Open a file read the CMOS into a buffer
mov dx,FileNamePtr ; DS:DX point to file
xor al,al ; AL=0 is attribute read/only
mov ah,03Dh ; DOS open function
int 21h
jc FileTrouble
mov bx,ax ; save handle
mov cx,128 ; read 128 bytes
lea dx,CMOSBuff ; buffer address
mov ah,3fH ; DOS read
int 21h
jc FileTrouble
cmp ax,128
jne FileTrouble
mov ah,3eh ; DOS close
int 21h
jc FileTrouble
ret
ReadCMOS EndP
EndIf
;===============================================================
if Generating eq CMOSSave
WriteCMOS Proc Near
; Create a file write CMOS to it
mov dx,FileNamePtr ; DS:DX point to file
xor cx,cx ; CX=0 is attribute
mov ah,03ch ; DOS create function
int 21h
jc FileTrouble
mov bx,ax ; SAVE HANDLE
MOV CX,128 ; write 128 bytes
lea dx,CMOSBuff ; buffer address
mov ah,40h ; DOS write
int 21h
jc FileTrouble
cmp ax,128
jne FileTrouble
mov ah,3eh ; DOS close
int 21h
jc FileTrouble
ret
WriteCMOS EndP
EndIf
;===============================================================
CODE ends ; end of code segment
end Start